package info;

import java.util.Date;
import java.util.List;

/**
 * The conference is a meeting by MSEE about a particular topic, which
 * may be further divided into categories of interest.  Experts and
 * amateurs meet up to discuss the topics and educate others.
 * <P>
 * While the size of a conference varies, and a different number of roles
 * are assigned, for the purposes of this software only Authors and
 * Program Chairs are known.  There can only be one Program Chair per
 * conference.
 * <P>
 * The review process is very deadline-driven, and thus a conference has
 * its own set of deadlines.  Once a Program Chair is assigned, he starts
 * the process by sending out a "Call for papers", which advertises for
 * manuscript submissions to enrich the conference.  Submissions must
 * happen before the submission deadline.  Additional deadlines include
 * the review deadline by which all reviews must be submitted, a
 * decision deadline by which the Program Chair must make a decision to
 * accept or reject all manuscript submissions, and a final editing
 * deadline by which authors of accepted manuscripts make final
 * adjustments and changes.  Once the process is complete, the Program
 * Chair publishes the manuscripts that were accepted, and the conference
 * can be under way as normal.
 * 
 * @author Aaron Chen * 
 * @version 3/21/2014
 */
public class Conference {
  
  /** The error message presented when the conference title field is not initialized. */
  private static final String ERROR_NAMELESS_CONFERENCE = "A conference cannot be nameless.";
  
  /** The number of dates a planned conference is expected to have. */
  private static final int NUM_DATES = 5;

  /** The index of the manuscript submission deadline in a List of dates. */
  private static final int DATE_MANUSCRIPT_SUBMISSION_DEADLINE = 0;
  
  /** The index of the review deadline in a List of dates. */
  private static final int DATE_REVIEW_DEADLINE = 1;
  
  /** The index of the Program Chair's decision deadline in a List of dates. */
  private static final int DATE_DECISION_DEADLINE = 2;
  
  /** The index of the final manuscript submission deadline in a List of dates. */
  private static final int DATE_FINAL_SUBMISSION_DEADLINE = 3;
  
  /** The index of the date when the conference goes live in a List of dates. */
  private static final int DATE_HOSTING = 4;
  

  /** The identification number of the conference. */
  private long my_id;
  
  /** The name of the conference. */
  private String my_title;
  
  /** The date the conference is live. */
  private Date my_hosting_date;
  
  /** The name of the venue that the conference takes place in. */
  private String my_hosting_venue;
  
  /** Informative and miscellaneous info associated with the conference. */
  private String my_info;
  
  /** The categories that this conference can be subdivided into. */
  private List<String> my_categories;
  
  /** The Program Chair responsible for this conference. */
  private long my_program_chair_id;
  
  /** The list of manuscripts that were accepted and published by the
   * Program Chair. */
  private List<Long> my_published_manuscript_ids;

  
  /** The deadline by which prospective Authors must submit their
   * manuscripts for review. */
  private Date my_submission_deadline;
  
  /** The deadline by which reviews for submitted manuscripts must be
   * completed. */
  private Date my_review_deadline;
  
  /** The deadline by which the Program Chair must make an acceptance
   * decision on submitted manuscripts. */
  private Date my_decision_deadline;
  
  /** The deadline by which Authors can make final changes to their
   * accepted manuscripts. */
  private Date my_final_submission_deadline;
  
  
  /**
   * Constructs a new Conference object with minimal fields initialized.
   * @param the_id    The associated identification number.
   * @param the_title The title by which the conference will be known by.
   * @param the_info  The information associated with the conference.
   * @param the_deadline The manuscript submission deadline.
   */
  public Conference(final long the_id,
                    final String the_title,
                    final String the_info,
                    final Date the_deadline) {
    if (the_title == null) {
      throw new IllegalArgumentException(ERROR_NAMELESS_CONFERENCE);
    }
    my_id = the_id;
    my_title = the_title;
    my_info = the_info;
    my_submission_deadline = the_deadline;
  }
  
  /**
   * Constructs a new Conference object with all fields initialized.
   * @param the_id            The associated identification number.
   * @param the_title         The title by which the conference will be known by.
   * @param the_hosting_venue The location which the conference will be hosted at.
   * @param the_info          The information associated with the conference.
   * @param the_categories    The categories that the conference has.
   * @param the_pc            The ID of the Program Chair responsible for this conference.
   * @param the_manuscripts   The ID of the manuscripts that are published in this conference.
   * @param the_dates         The list of dates and deadlines that the conference abides by.
   */
  public Conference(final long the_id,
                    final String the_title,
                    final String the_hosting_venue,
                    final String the_info,
                    final List<String> the_categories,
                    final long the_pc,
                    final List<Long> the_manuscripts,
                    final List<Date> the_dates) {
    this(the_id, the_title, the_info, the_dates.get(DATE_MANUSCRIPT_SUBMISSION_DEADLINE));
    checkArguments(the_title, the_dates);
    my_hosting_venue = the_hosting_venue;
    my_categories = the_categories;
    my_program_chair_id = the_pc;
    my_published_manuscript_ids = the_manuscripts;
    assignDateFields(the_dates);
  }
  
  /**
   * Checks the arguments passed into the constructor.
   * @param the_title The title by which the conference will be known by.
   * @param the_dates The list of dates and deadlines that the conference abides by.
   */
  private void checkArguments(final String the_title, final List<Date> the_dates) {
    if (!checkDates(the_dates)) {
      throw new IllegalArgumentException("Conference dates are not in correct order.");
    }
    if (the_title == null) {
      throw new IllegalArgumentException(ERROR_NAMELESS_CONFERENCE);
    }
  }
  
  /**
   * Parses the List<Date> object passed as a constructor argument and assigns the
   * conference fields the appropriate values.
   * @param the_dates The list of dates and deadlines that the conference abides by.
   */
  private void assignDateFields(final List<Date> the_dates) {
    my_hosting_date = the_dates.get(DATE_HOSTING);
    my_submission_deadline = the_dates.get(DATE_MANUSCRIPT_SUBMISSION_DEADLINE);
    my_review_deadline = the_dates.get(DATE_REVIEW_DEADLINE);
    my_decision_deadline = the_dates.get(DATE_DECISION_DEADLINE);
    my_final_submission_deadline = the_dates.get(DATE_FINAL_SUBMISSION_DEADLINE);
  }
  
  /**
   * Checks the set of dates to see if they are in valid order.
   * @param the_dates The set of dates and deadlines the conference abides by.
   * @return False if any of the dates are in the wrong order including equivalent
   * dates, or there are not 5 dates; true otherwise.
   */
  private boolean checkDates(final List<Date> the_dates) {
    boolean is_valid = true;
    if (the_dates.size() != NUM_DATES) {
      is_valid = false;
    }
    for (int i = 1; i < the_dates.size(); i++) {
      final Date d1 = the_dates.get(i - 1);
      final Date d2 = the_dates.get(i);
      if (!d1.before(d2)) {
        is_valid = false;
      }
    }
    return is_valid;
  }
  
  /**
   * Returns the identification number of the conference.
   * @return The conference ID.
   */
  public long getID() {
    return my_id;
  }
  /**
   * Sets the identification number of the conference.
   * @param the_id The conference ID.
   */
  public void setID(final long the_id) {
    my_id = the_id;
  }
  /**
   * Returns the name of the conference.
   * @return The conference title.
   */
  public String getTitle() {
    return my_title;
  }
  /**
   * Returns the conference's hosting date.
   * @return The hosting date.
   */
  public Date getHostingDate() {
    return my_hosting_date;
  }
  /**
   * Returns the name of the venue that the conference takes place in.
   * @return The conference hosting venue.
   */
  public String getHostingVenue() {
    return my_hosting_venue;
  }
  /**
   * Returns informative and miscellaneous info associated with the conference.
   * @return The conference information text.
   */
  public String getInfo() {
    return my_info;
  }
  /**
   * Returns the categories that this conference can be subdivided into.
   * @return The conference categories.
   */
  public List<String> getCategories() {
    return my_categories;
  }
  /**
   * Returns the Program Chair responsible for this conference.
   * @return The conference Program Chair's ID.
   */
  public long getProgramChairID() {
    return my_program_chair_id;
  }
  /**
   * Returns the list of manuscripts that were accepted and published by the
   * Program Chair. 
   * @return The list of IDs of the published manuscripts.
   */
  public List<Long> getPublishedManuscripts() {
    return my_published_manuscript_ids;
  }

  /**
   * Returns the deadline by which prospective Authors must submit their
   * manuscripts for review.
   * @return The manuscript submission deadline.
   */
  public Date getSubmissionDeadline() {
    return my_submission_deadline;
  }
  /**
   * Returns the deadline by which reviews for submitted manuscripts must be
   * completed.
   * @return The review deadline.
   */
  public Date getReviewDeadline() {
    return my_review_deadline;
  }
  /**
   * Returns the deadline by which the Program Chair must make an acceptance
   * decision on submitted manuscripts.
   * @return The decision deadline.
   */
  public Date getDecisionDeadline() {
    return my_decision_deadline;
  }
  /**
   * Returns the deadline by which Authors can make final changes to their
   * accepted manuscripts.
   * @return The final submission deadline.
   */
  public Date getFinalSubmissionDeadline() {
    return my_final_submission_deadline;
  }
  
  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    return my_title;
  }

}
